/*
 * Copyright 2014 Hieu Rocker
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.rockerhieu.emojicon;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.*;
import android.widget.EditText;
import com.rockerhieu.emojicon.emoji.*;

import java.util.Arrays;
import java.util.List;

/**
 * @author Hieu Rocker (rockerhieu@gmail.com).
 */
public class EmojiconsFragment extends Fragment implements
		ViewPager.OnPageChangeListener {
	private OnEmojiconBackspaceClickedListener mOnEmojiconBackspaceClickedListener;
	private int mEmojiTabLastSelectedIndex = -1;
	private View[] mEmojiTabs;

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View view = inflater.inflate(R.layout.emojicons, container, false);
		final ViewPager emojisPager = (ViewPager) view
				.findViewById(R.id.emojis_pager);
		emojisPager.setOnPageChangeListener(this);
		EmojisPagerAdapter emojisAdapter = new EmojisPagerAdapter(
				getFragmentManager(), Arrays.asList(
						EmojiconGridFragment.newInstance(People.DATA),
						EmojiconGridFragment.newInstance(Nature.DATA),
						EmojiconGridFragment.newInstance(Objects.DATA),
						EmojiconGridFragment.newInstance(Places.DATA),
						EmojiconGridFragment.newInstance(Symbols.DATA)));
		emojisPager.setAdapter(emojisAdapter);

		mEmojiTabs = new View[5];
		mEmojiTabs[0] = view.findViewById(R.id.emojis_tab_0_people);
		mEmojiTabs[1] = view.findViewById(R.id.emojis_tab_1_nature);
		mEmojiTabs[2] = view.findViewById(R.id.emojis_tab_2_objects);
		mEmojiTabs[3] = view.findViewById(R.id.emojis_tab_3_cars);
		mEmojiTabs[4] = view.findViewById(R.id.emojis_tab_4_punctuation);
		for (int i = 0; i < mEmojiTabs.length; i++) {
			final int position = i;
			mEmojiTabs[i].setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					emojisPager.setCurrentItem(position);
				}
			});
		}
		view.findViewById(R.id.emojis_backspace).setOnTouchListener(
				new RepeatListener(1000, 50, new View.OnClickListener() {
					@Override
					public void onClick(View v) {
						if (mOnEmojiconBackspaceClickedListener != null) {
							mOnEmojiconBackspaceClickedListener
									.onEmojiconBackspaceClicked(v);
						}
					}
				}));
		onPageSelected(0);
		return view;
	}

	@Override
	public void onAttach(Activity activity) {
		super.onAttach(activity);
		if (getActivity() instanceof OnEmojiconBackspaceClickedListener) {
			mOnEmojiconBackspaceClickedListener = (OnEmojiconBackspaceClickedListener) getActivity();
		} else if (getParentFragment() instanceof OnEmojiconBackspaceClickedListener) {
			mOnEmojiconBackspaceClickedListener = (OnEmojiconBackspaceClickedListener) getParentFragment();
		} else {
			throw new IllegalArgumentException(activity
					+ " must implement interface "
					+ OnEmojiconBackspaceClickedListener.class.getSimpleName());
		}
	}

	@Override
	public void onDetach() {
		mOnEmojiconBackspaceClickedListener = null;
		super.onDetach();
	}

	public static void input(EditText editText, Emojicon emojicon) {
		if (editText == null || emojicon == null) {
			return;
		}

		int start = editText.getSelectionStart();
		int end = editText.getSelectionEnd();
		if (start < 0) {
			editText.append(emojicon.getEmoji());
		} else {
			editText.getText().replace(Math.min(start, end),
					Math.max(start, end), emojicon.getEmoji(), 0,
					emojicon.getEmoji().length());
		}
	}

	public static void backspace(EditText editText) {
		KeyEvent event = new KeyEvent(0, 0, 0, KeyEvent.KEYCODE_DEL, 0, 0, 0,
				0, KeyEvent.KEYCODE_ENDCALL);
		editText.dispatchKeyEvent(event);
	}

	@Override
	public void onPageScrolled(int i, float v, int i2) {
	}

	@Override
	public void onPageSelected(int i) {
		if (mEmojiTabLastSelectedIndex == i) {
			return;
		}
		switch (i) {
		case 0:
		case 1:
		case 2:
		case 3:
		case 4:
			if (mEmojiTabLastSelectedIndex >= 0
					&& mEmojiTabLastSelectedIndex < mEmojiTabs.length) {
				mEmojiTabs[mEmojiTabLastSelectedIndex].setSelected(false);
			}
			mEmojiTabs[i].setSelected(true);
			mEmojiTabLastSelectedIndex = i;
			break;
		}
	}

	@Override
	public void onPageScrollStateChanged(int i) {
	}

	private static class EmojisPagerAdapter extends FragmentStatePagerAdapter {
		private List<EmojiconGridFragment> fragments;

		public EmojisPagerAdapter(FragmentManager fm,
				List<EmojiconGridFragment> fragments) {
			super(fm);
			this.fragments = fragments;
		}

		@Override
		public Fragment getItem(int i) {
			return fragments.get(i);
		}

		@Override
		public int getCount() {
			return fragments.size();
		}
	}

	/**
	 * A class, that can be used as a TouchListener on any view (e.g. a Button).
	 * It cyclically runs a clickListener, emulating keyboard-like behaviour.
	 * First click is fired immediately, next before initialInterval, and
	 * subsequent before normalInterval.
	 * <p/>
	 * <p>
	 * Interval is scheduled before the onClick completes, so it has to run
	 * fast. If it runs slow, it does not generate skipped onClicks.
	 */
	public static class RepeatListener implements View.OnTouchListener {

		private Handler handler = new Handler();

		private int initialInterval;
		private final int normalInterval;
		private final View.OnClickListener clickListener;

		private Runnable handlerRunnable = new Runnable() {
			@Override
			public void run() {
				if (downView == null) {
					return;
				}
				handler.removeCallbacksAndMessages(downView);
				handler.postAtTime(this, downView, SystemClock.uptimeMillis()
						+ normalInterval);
				clickListener.onClick(downView);
			}
		};

		private View downView;

		/**
		 * @param initialInterval
		 *            The interval before first click event
		 * @param normalInterval
		 *            The interval before second and subsequent click events
		 * @param clickListener
		 *            The OnClickListener, that will be called periodically
		 */
		public RepeatListener(int initialInterval, int normalInterval,
				View.OnClickListener clickListener) {
			if (clickListener == null)
				throw new IllegalArgumentException("null runnable");
			if (initialInterval < 0 || normalInterval < 0)
				throw new IllegalArgumentException("negative interval");

			this.initialInterval = initialInterval;
			this.normalInterval = normalInterval;
			this.clickListener = clickListener;
		}

		public boolean onTouch(View view, MotionEvent motionEvent) {
			switch (motionEvent.getAction()) {
			case MotionEvent.ACTION_DOWN:
				downView = view;
				handler.removeCallbacks(handlerRunnable);
				handler.postAtTime(handlerRunnable, downView,
						SystemClock.uptimeMillis() + initialInterval);
				clickListener.onClick(view);
				return true;
			case MotionEvent.ACTION_UP:
			case MotionEvent.ACTION_CANCEL:
			case MotionEvent.ACTION_OUTSIDE:
				handler.removeCallbacksAndMessages(downView);
				downView = null;
				return true;
			}
			return false;
		}
	}

	public interface OnEmojiconBackspaceClickedListener {
		void onEmojiconBackspaceClicked(View v);
	}
}
